package com.zkh.myutils.io.excel;

import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

import com.zkh.myutils.io.IOUtils;
import com.zkh.myutils.io.excel.data.WorkbookData;
import com.zkh.myutils.io.excel.parser.ExcelParser;
import com.zkh.myutils.io.excel.parser.XLSXParser;
import com.zkh.myutils.io.file.FileUtils;

/**
 * 工作簿读对象
 * @author zkh
 */
public class WorkbookReader implements Closeable{
	//文件流
	private InputStream inputStream;
	private BufferedInputStream bufferedInputStream;
	//数据
	private WorkbookData data;
	
	/**
	 * 构造方法
	 * @param filepath 待读取的文件的路径
	 */
	public WorkbookReader(String filepath) throws IOException {
		//获取后缀
		String suffix = FileUtils.getSuffix(filepath);
		//检查类型
		if("xls".equalsIgnoreCase(suffix)) {
			throw new WorkbookException("不支持XLS格式的文件");
		}
		if(!"xlsx".equalsIgnoreCase(suffix)) {
			throw new WorkbookException("仅支持XLSX格式的文件");
		}
		//解析流
		parseStream(Files.newInputStream(Paths.get(filepath)));
	}
	
	/**
	 * 构造方法
	 * @param inputStream 待读取的文件流
	 */
	public WorkbookReader(InputStream inputStream) throws IOException {
		//解析流
		parseStream(inputStream);
	}
	
	/**
	 * 初始化
	 */
	private void parseStream(InputStream inputStream) throws IOException {
		//保存流
		this.inputStream = inputStream;
		this.bufferedInputStream = new BufferedInputStream(inputStream);
		//检查类型
		checkType(inputStream);
		//初始化解析器
		ExcelParser parser = new XLSXParser(this.bufferedInputStream);
		//解析
		data = parser.parse();
	}
	
	//检查类型
	private void checkType(InputStream inputStream) throws IOException {
		//读取文件头部数据，以确定文件类型是否是Excel
		byte[] bytes = new byte[4];
		this.bufferedInputStream.mark(0);
		this.bufferedInputStream.read(bytes);
		this.bufferedInputStream.reset();
		//头部数据转十六进制字符
		StringBuilder sb = new StringBuilder();
		for(byte b: bytes) {
			String hex = Integer.toHexString(b & 0xFF);
			if(hex.length()<2) {
				sb.append(0);
			}
			sb.append(hex);
		}
		//目标十六进制字符
		String type = sb.toString();
		//检查类型
		if("d0cf11e0".equals(type)) {
			throw new WorkbookException("不支持XLS格式的文件");
		}
		if(!"504b0304".equals(type)) {
			throw new WorkbookException("解析失败，仅支持XLSX格式的文件");
		}
	}

	/**
	 * 获取数据
	 */
	public WorkbookData getData() {
		return data;
	}

	/**
	 * 关闭流
	 */
	public void close() throws IOException {
		IOUtils.closeQuietly(bufferedInputStream, inputStream);
	}
}
